package edu.compila.client.compila;

public class Lexico {
	
	private String fonte; //
		
	private String atual; //O texto que será consumido ao extrair os tokens

	private TabelaSimbolos tabela;
	
	private String trecho = "";
	
	private Boolean has = true;
	
	public Lexico(String fonte,TabelaSimbolos tabela) {
		this.fonte = fonte;
		this.atual = fonte;
		this.tabela = tabela;
	}

	
	//Retornar true se ainda há tokens para retornar
	public Boolean hasNext(){
		return has;
	}
	
	//Remove espaços em branco do codigo fonte
	public String retirarEspacos(){
		String tmp = fonte;
		String resultado = "";
		tmp = tmp.replaceAll(" ", "");
		tmp = tmp.replaceAll("\t", "");
		tmp = tmp.replaceAll("\r", "");
		
		for(int c = 0; c<tmp.length();c++){
			if(!tmp.substring(c,c + 1).equals("\n")){
				resultado += tmp.substring(c,c + 1);
			} 
		}
		atual = resultado;
		return resultado;
	}
	
	public Token nextToken() {
		Padrao p;
		Token token;
		Character c;
		
		while(true) {
			c = getChar();
			//consumir o texto original
			if(atual.length() > 0) {
				trecho += c;
				atual = atual.substring(1);
			}
			if(c == null) {
				return new Token(Padrao.EOF, "EOF");
			}
			
			//Verifica o trecho + 1 na tabela de simbolos
			p = tabela.contem(trecho + getChar());
			if(p != null) {
				trecho += getChar();
				atual = atual.substring(1);
				//está na tabela
				token = new Token(p, trecho);
				trecho = "";
				return token;
			}

			//Verifica o trecho na tabela de simbolos
			p = tabela.contem(trecho);
			if(p != null) {
				//está na tabela
				token = new Token(p, trecho);
				trecho = "";
				return token;
			}
			
			if(c == null) return null;
			
			//Verificar se é literal
			if(c.toString().equals("\"")) {
				do{
					c = getChar();
					if(c == null) return null;
					//consome a entrada
					if(atual.length() > 0) {
						atual = atual.substring(1);
						trecho += c.toString();
					}
				}while(!c.toString().equals("\""));
				token = new Token(Padrao.LITERAL,trecho.replaceAll("\"", ""));
				trecho = "";
				return token;
			}
			
			//Verifica se é numero
			if(Character.isDigit(c)){
				while(Character.isDigit(c)){
		
					//Verifica o trecho + 1 na tabela de simbolos
					p = tabela.contem(trecho + getChar());
					if(p != null) {
						//está na tabela é : ou ;
						token = new Token(Padrao.NUMERO, trecho);
						trecho = "";
						return token;
					}

					//Verifica o trecho na tabela de simbolos
					p = tabela.contem(getChar().toString());
					if(p != null) {
						//está na tabela é : ou ;
						token = new Token(Padrao.NUMERO, trecho);
						trecho = "";
						return token;
					}
					
					c = getChar();
					//retorna null
					if(c == null) return new Token(Padrao.ERRO_LEXICO, "ERRO");

					//consome a entrada
					if(atual.length() > 0) {
						atual = atual.substring(1);
						trecho += c.toString();
					}
					
				}
			}
			
			//Verifica se é identificador
			if(c.toString().equals("_") || Character.isLetter(c)){
				while(c.toString().equals("_") || Character.isLetter(c) || Character.isDigit(c)){
					c = getChar();
					//retorna null
					if(c == null) return new Token(Padrao.ERRO_LEXICO, "ERRO");

					//Verifica o trecho na tabela de simbolos
					p = tabela.contem(trecho);
					if(p != null) {
						//está na tabela
						token = new Token(p, trecho);
						trecho = "";
						return token;
					} 
					p = tabela.contem(getChar().toString());
					if( p != null){
						//está na tabela é ; : ou &
						token = new Token(Padrao.IDENTIFICADOR, trecho);
						trecho = "";
						return token;
					}
					if(!Character.isLetter(c)){
						//está na tabela é ; : ou &
						token = new Token(Padrao.IDENTIFICADOR, trecho);
						trecho = "";
						return token;
					}
					//consome a entrada
					if(atual.length() > 0) {
						atual = atual.substring(1);
						trecho += c.toString();
					}
					
					
					
				}
			}
			
		}
	}
	private Character getChar() {
		if(atual.length() > 0) {
			Character c = atual.charAt(0);
			return c;
		} else {
			has = false;
			return null;
		}
	}

	
	//Remove comentarios do codigo fonte
	public String retirarComentarios(){
		String tmp = atual;
		String trecho = "";
		String resultado = "";
		Integer conta =0;
		
		for (int c= 0; c< tmp.length();c++) {
			trecho += tmp.substring(c, c + 1);
			conta++;
			if(trecho.startsWith("#-") && trecho.endsWith("-#")) {
				resultado = tmp.substring(conta, tmp.length());
				tmp = resultado;
				conta = 0;
			} 
		}
		atual = resultado;
		return resultado;
	}
		
	
	
}
